package com.wanshu.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wanshu.common.execption.BizException;
import com.wanshu.common.util.PageUtils;
import com.wanshu.sys.entity.SysMenu;
import com.wanshu.sys.mapper.SysMenuMapper;
import com.wanshu.sys.model.SysMenuQueryDto;
import com.wanshu.sys.service.ISysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 菜单管理 服务实现类
 * </p>
 *
 * @author 波哥
 * @since 2023-05-09
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Override
    public PageUtils<SysMenu> listPage(SysMenuQueryDto dto) {
        //分页查询 一级菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper();
        wrapper.eq(SysMenu::getParentId, 0)
                .like(StringUtils.isNotBlank(dto.getName()), SysMenu::getName, dto.getName())
                .like(StringUtils.isNotBlank(dto.getLabel()), SysMenu::getLabel, dto.getLabel())
                .orderByAsc(SysMenu::getOrderNum); //升序
        Page<SysMenu> page = this.page(dto.page(), wrapper);
        //查询当前页每个一级菜单下的二级菜单并关联到一级菜单中
        List<SysMenu> list = page.getRecords();
/*        List<SysMenu> collect = list.stream().map(item -> {
            Long menuId = item.getMenuId();
            //标记是否可以删除
            markCanBeDetele(item);
            //查询子菜单
            List<SysMenu> childrens = queryMenuByPId(menuId);
            for (SysMenu children : childrens) {
                //标记子菜单是否可以删除
                markCanBeDetele(children);
            }
            //关联父子菜单
            item.setChildren(childrens);
            //item.setHasChildren(!childrens.isEmpty()); 延迟加载时使用，那时子菜单单独不需要一起返回，要单独查询子菜单
            return item;
        }).collect(Collectors.toList());
          page.setRecords(collect);
        */
        //优化：使用递归
        for (SysMenu sysMenu : list) {
            getChildrenMenu(sysMenu);
        }
        page.setRecords(list);
        return new PageUtils(page);
    }


    @Override
    public List<SysMenu> listParentMenu() {
        List<SysMenu> sysMenus = queryMenuByPId(0L);
        return sysMenus;
    }

    @Override
    public void saveSysMenu(SysMenu sysMenu) {
        if (sysMenu.getMenuId() != null) {
            //更新操作
            updateById(sysMenu);
        } else {
            //父菜单为空，则说明是根菜单（根菜单的父菜单都为0）
            if (sysMenu.getParentId() == null) {
                sysMenu.setParentId(0L);
            }
            //新增操作
            save(sysMenu);
        }
    }

    @Override
    public SysMenu queryMenuById(Long menuId) {
        return baseMapper.selectById(menuId);
    }

    @Override
    public void deleteById(Long menuId) {
        int c = sysMenuMapper.countInUse(menuId);
        if (c > 0) {
            throw new BizException("菜单包含未删除的子菜单或者菜单已经被分配给角色，请检查后再删除！~");
        }
        sysMenuMapper.deleteById(menuId);
    }

    /**
     * 递归子菜单
     *
     * @param menu 菜单
     * @return {@link SysMenu }
     * @author 张颖辉（zyh）
     * @date 2023/07/12
     * @version 1.0.0
     */
    @Override
    public SysMenu getChildrenMenu(SysMenu menu) {
        // 标记是否可以detele
        markCanBeDetele(menu);
        //获取子菜单
        List<SysMenu> sysMenus = queryMenuByPId(menu.getMenuId());
        if (sysMenus.size() == 0) {
            return menu;
        }
        //设置子菜单
        menu.setChildren(sysMenus);
        //遍历子菜单，递归子菜单的子菜单
        for (SysMenu sysMenu : sysMenus) {
            getChildrenMenu(sysMenu);
        }
        return menu;
    }

    @Override
    public List<SysMenu> getUserMenus() {
        //获取当前的登录用户
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        String userName = (String) token.getPrincipal();
        List<SysMenu> menus = getUserMenusByPid(userName, 0L);
        return menus;
    }

    /**
     * 由pid获取用户菜单
     *
     * @param userName 用户名
     * @param parentId 父id
     * @return {@link List }<{@link SysMenu }>
     * @author 张颖辉（zyh）
     * @date 2023/07/18
     * @version 1.0.0
     */
    private List<SysMenu> getUserMenusByPid(String userName, Long parentId) {
        List<SysMenu> menus = baseMapper.selectMenuByUserNameAndParentId(userName, parentId);
        for (SysMenu menu : menus) {
            // 标记是否可以detele
            markCanBeDetele(menu);
            // 递归查询处理子菜单
            List<SysMenu> subs = getUserMenusByPid(userName, menu.getMenuId());
            menu.setChildren(subs);
        }
        return menus;
    }

    /**
     * 标记是否可以detele
     *
     * @param menu 菜单
     * @author 张颖辉（zyh）
     * @date 2023/07/12
     * @version 1.0.0
     */
    private void markCanBeDetele(SysMenu menu) {
        int subc = sysMenuMapper.countInUse(menu.getMenuId());
        //未被使用，并且不是首页，才可以删除
        if (subc == 0 && !(StringUtils.isNotBlank(menu.getPath()) && menu.getPath().equals("/"))) {
            menu.setCanbeDelete(true);
        }
    }

    /**
     * 查询菜单由pid
     *
     * @param menuId 菜单id
     * @return {@link List }<{@link SysMenu }>
     * @author 张颖辉（zyh）
     * @date 2023/07/12
     * @version 1.0.0
     */
    private List<SysMenu> queryMenuByPId(Long menuId) {
        LambdaQueryWrapper<SysMenu> wrappe = new LambdaQueryWrapper();
        wrappe.eq(SysMenu::getParentId, menuId)
                .orderByAsc(SysMenu::getOrderNum); //升序
        return list(wrappe);
    }
}
